package com.rimi.bbs.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rimi.bbs.bean.Card;
import com.rimi.bbs.bean.JsonResult;
import com.rimi.bbs.bean.Replies;
import com.rimi.bbs.bean.User;
import com.rimi.bbs.service.CardService;
import com.rimi.bbs.service.MailService;
import com.rimi.bbs.service.RepliesService;
import com.rimi.bbs.service.UserService;
import com.wf.captcha.utils.CaptchaUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author jerry
 * @since 2019-02-24
 */
@Controller
@RequestMapping("/user")
public class UserController {

    private Logger logger= LoggerFactory.getLogger(getClass());

    @Autowired
    private UserService userService;

    @Autowired
    private CardService cardService;

    @Autowired
    private MailService mailService;

    @Autowired
    private RepliesService repliesService;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Value("${file.uploadFolder}")
    private String uploadFolder;

    @Autowired
    private SessionRegistry sessionRegistry;

    @GetMapping("/out")
    @ResponseBody
    public Object out(){
        String username="jerry";
        List<Object> users = sessionRegistry.getAllPrincipals(); // 获取session中所有的用户信息
        for (Object principal : users) {
            if (principal instanceof User) {
                final User loggedUser = (User) principal;
                if (username.equals(loggedUser.getUsername())) {
                    List<SessionInformation> sessionsInfo = sessionRegistry.getAllSessions(principal, false); // false代表不包含过期session
                    if (null != sessionsInfo && sessionsInfo.size() > 0) {
                        for (SessionInformation sessionInformation : sessionsInfo) {
                            sessionInformation.expireNow();
                        }
                    }
                }
            }
        }
        return "hello";
    }

    @GetMapping("/username/{username}")
    public String userName(@PathVariable String username,Model model){
        User user = userService.getUserByName(username);
        if(user==null){
            return "/other/404";
        }
        //通过用户信息 查询该用户对用的提问帖
        //查询该用户回答帖
        List<Card> cardList = cardService.list(new QueryWrapper<Card>()
                .eq("user_id", user.getUserId())
                .orderByDesc("card_id", "card_create_time"));
        model.addAttribute("cardList",cardList);
        //回答
        List<Replies> repliesList = repliesService.getRepliesByUserId(user.getUserId());
        model.addAttribute("repliesList",repliesList);
        model.addAttribute("user",user);
        return "/user/home";
    }

    /**
     * @param email
     * @param vercode
     * @param model
     * @param session
     * @return
     *  邮箱链接请求验证
     */
    @GetMapping("/forget/repass")
    public String forget(String email,String vercode,Model model,HttpSession session){
        if(StringUtils.isEmpty(email)||StringUtils.isEmpty(vercode)){
            logger.info("重置密码：邮箱或验证码为空");
            return "/user/forget";
        }
        //判断验证码
        Object uuid = session.getAttribute("vercode");
        logger.info("uuid:"+uuid);
        if(StringUtils.isEmpty(uuid)||StringUtils.isEmpty(vercode)||!uuid.equals(vercode)){
            model.addAttribute("pass",3);
            return "/user/forget";
        }
        //获取用户信息
        //查看邮箱是否存在
        User user = userService.getUserByEmailName(email);
        if(user==null){
            model.addAttribute("pass",3);
            return "/user/forget";
        }
        //1 重置密码 2、连接失效 3、非法链接
        model.addAttribute("pass",1);
        model.addAttribute("user",user);
        //删除验证码 只能使用一次
        //session.removeAttribute("vercode");
        return "/user/forget";
    }

    /**
     * @param email
     * @param vercode
     * @param request
     * @param session
     * @return
     *  发送重置密码邮件
     */
    @PostMapping("/forget/")
    @ResponseBody
    public Object forget(String email,String vercode,HttpServletRequest request,HttpSession session){
        if(StringUtils.isEmpty(email)){
            return JsonResult.error("邮箱地址不能为空");
        }
        if(StringUtils.isEmpty(vercode)){
            return JsonResult.error("验证码不能为空");
        }
        //验证码比较
        if (!CaptchaUtil.ver(vercode, request)) {
            CaptchaUtil.clear(request);
            return JsonResult.error("验证码不正确");
        }
        //查看邮箱是否存在
        User user = userService.getUserByEmailName(email);
        if(user==null){
            return JsonResult.error("该邮箱不存在");
        }
        //生成UUID用作验证 + email 修改人 + 用户ID 三者匹配才做修改
        String uuid = UUID.randomUUID().toString();
        session.setAttribute("vercode",uuid);
        //发送验证邮件
        String content="该链接有效期半小时,并且只能使用一次！！<br>重置密码 : https://rimi.liangdian.online/user/forget/repass?uid"+System.currentTimeMillis()+"&email="+email+"&vercode="+uuid;
        logger.info("重置密码邮件内容:"+content);
        boolean b = mailService.sendHtmlMail(email, "RIMI论坛-重置密码", content);
        if(!b){
            return JsonResult.error("服务器邮件发送失败,请稍后重试");
        }
        return JsonResult.ok("邮件发送成功,请查看邮件").put("action","/user/login.html");
    }

    /**
     * @param email
     * @param username
     * @param pass
     * @param repass
     * @param vercode
     * @param request
     * @return
     *    重置密码修改
     */
    @PostMapping("/forget/repass")
    @ResponseBody
    public Object forgetRepass(String email,String username,String pass,String repass,String vercode,HttpServletRequest request){
        if(StringUtils.isEmpty(email)||StringUtils.isEmpty(username)){
            return JsonResult.error("表单信息有误，请重试");
        }
        if(StringUtils.isEmpty(pass)||StringUtils.isEmpty(repass)){
            return JsonResult.error("新密码或确认密码不能为空");
        }
        //新密码长度
        if(pass.length()<6||pass.length()>16){
            return JsonResult.error("密码长度不符合规则");
        }
        //新密码与重复密码
        if (!pass.equals(repass)){
            return JsonResult.error("新密码与确认密码不一致");
        }
        //验证码比较
        if (!CaptchaUtil.ver(vercode, request)) {
            CaptchaUtil.clear(request);
            return JsonResult.error("验证码不正确");
        }
        User user = userService.getOne(new QueryWrapper<User>()
                .eq("user_name", username)
                .eq("user_email", email));
        if(user == null){
            return JsonResult.error("该用户不存在");
        }
        boolean b = userService.updateUserByEmail(user.setUserPassword(pass));
        if(!b){
            return JsonResult.error("修改密码失败,请重试");
        }
        return JsonResult.ok("密码修改成功").put("action","/user/login.html");
    }

    /**
     * @param nowpass
     * @param pass
     * @param repass
     * @return
     * 修改密码
     */
    @PostMapping("/repass")
    @ResponseBody
    public Object repass(String nowpass,String pass,String repass){
        //不为空
        if(StringUtils.isEmpty(nowpass)||StringUtils.isEmpty(pass)||StringUtils.isEmpty(repass)){
            return JsonResult.error("请输入必填项");
        }
        //新密码长度
        if(pass.length()<6||pass.length()>16){
            return JsonResult.error("密码长度不符合规则");
        }
        //新密码与重复密码
        if(!pass.equals(repass)){
            return JsonResult.error("新密码与重复密码输入不一致");
        }
        User currUser = getCurrUser();
        //原密码与新密码一致
        if(nowpass.equals(pass)){
            return JsonResult.error("原密码与新密码一致");
        }
        logger.info("原密码"+currUser.getUserPassword());
        //原密码是否正确
        if(!passwordEncoder.matches(nowpass,currUser.getUserPassword())){
            return JsonResult.error("原密码输入错误");
        }
        //修改数据库
        boolean b = userService.updateUserPassword(getCurrUser().getUserId(), pass);
        if(!b){
            return JsonResult.error("密码修改失败,请刷新重试");
        }
        //退出登录
        return JsonResult.ok("密码修改成功").put("action","/logout");
    }

    /**
     * @return
     * 用户中心：我的发帖
     * 待完成:我的收藏
     */
    @GetMapping("/index")
    public String index(Model model){
        //获取当前登录用户
        List<Card> list = cardService.list(new QueryWrapper<Card>()
                .eq("user_id", getCurrUser().getUserId())
                .eq("card_delete", 1));

        model.addAttribute("cardList",list);
        model.addAttribute("pageType","/user/index");
        return "/user/index";
    }

    @PostMapping("/edit")
    @ResponseBody
    public Object edit(User user){
        boolean b = userService.updateById(user);
        if(b){
            //更改session中的信息
            updateCurrUser(user);
            logger.info("执行用户修改操作");
            return JsonResult.ok("修改成功").put("action","/user/set.html");
        }
        return JsonResult.error("服务器异常修改失败");
    }

    /**
     * @param file
     * @param request
     * @return
     * 头像上传
     */
    @PostMapping("/upload")
    @ResponseBody
    public Object  upload(@RequestParam("file") MultipartFile file, HttpServletRequest request){
        if (file.isEmpty()) {
            return JsonResult.error("上传失败，请选择文件");
        }
        logger.info("文件保存"+uploadFolder);
        //文件保存路径
        String path = uploadFolder+"/images/";
        //文件名
        String fileName=System.currentTimeMillis()+file.getOriginalFilename();
        //
        File file1 = new File(path, fileName);
        try {
            //父级目录
            if(!file1.getParentFile().exists()){
                file1.getParentFile().mkdirs();
            }
            file.transferTo(file1);
            //修改数据库
            boolean b = userService.updateById(new User().setUserId(getCurrUser().getUserId()).setUserImage("/images/"+fileName));
            if(!b){
                return JsonResult.error("图片路径保存失败,图片名称过长");
            }
            getCurrUser().setUserImage("/images/"+fileName);
            return JsonResult.ok("文件上传成功").put("url","/images/"+fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return JsonResult.error("头像修改失败");
    }

    /**
     * @param user 用户信息
     * @param vercode 验证码
     * @param repass  重复密码
     * @param request
     * @return
     * 用户注册方法
     */
    @PostMapping("/register")
    @ResponseBody
    public Object  register(User user, String vercode, String repass, HttpServletRequest request){
        if(user==null){
            return JsonResult.error("请输入注册信息");
        }
        //验证码比较
        if (!CaptchaUtil.ver(vercode, request)) {
            CaptchaUtil.clear(request);
            return JsonResult.error("验证码不正确");
        }
        //密码长度
        if(user.getUserPassword().length()<6){
            return JsonResult.error("密码长度太短");
        }
        //密码长度
        if(user.getUserPassword().length()>16){
            return JsonResult.error("密码长度太长");
        }
        //比较新旧密码是否一致
        if(repass==null||!repass.equals(user.getUserPassword())){
            return JsonResult.error("新旧密码不一致");
        }
        //邮箱是否注册过
        User emailName = userService.getUserByEmailName(user.getUserEmail());
        if(emailName!=null){
            return JsonResult.error("该邮箱已注册过");
        }
        //用户名是否重复
        User userByName = userService.getUserByName(user.getUsername());
        if(userByName!=null){
            return JsonResult.error("该昵称已被使用");
        }
        boolean save = userService.register(user);
        if(save){
            return JsonResult.ok("注册成功").put("action","/user/login.html");
        }
        return JsonResult.error("注册失败，请重试");
    }


    /**
     * @return 获取当前用户信息
     */
    private User getCurrUser(){
        //获取当前登录用户
        User u = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return u;
    }

    /**
     * @param user
     * 修改session中的当前用户信息
     */
    private void updateCurrUser(User user){
        if(user==null){
            return;
        }
        User currUser = getCurrUser();
        //邮箱
        if(!StringUtils.isEmpty(user.getUserEmail())){
            currUser.setUserEmail(user.getUserEmail());
        }
        //用户名
        if(!StringUtils.isEmpty(user.getUsername())){
            currUser.setUserName(user.getUsername());
        }
        //头像
        if(!StringUtils.isEmpty(user.getUserImage())){
            currUser.setUserImage(user.getUserImage());
        }
        //签名
        if(!StringUtils.isEmpty(user.getUserAutograph())){
            currUser.setUserAutograph(user.getUserAutograph());
        }
        //城市
        if(!StringUtils.isEmpty(user.getUserAddress())){
            currUser.setUserAddress(user.getUserAddress());
        }
        //性别
        if(!StringUtils.isEmpty(user.getUserSex())){
            currUser.setUserSex(user.getUserSex());
        }
    }

}

